package cn.kgc.springboot.service.impl;

import cn.kgc.springboot.dto.UserPageDTO;
import cn.kgc.springboot.entity.*;
import cn.kgc.springboot.mapper.*;
import cn.kgc.springboot.util.CodeMsg;
import cn.kgc.springboot.util.ResponseResult;
import cn.kgc.springboot.util.SaltUtil;
import cn.kgc.springboot.util.TreeUtil;
import cn.kgc.springboot.vo.PermissionVO;
import cn.kgc.springboot.vo.UserVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.kgc.springboot.service.UserService;
import com.mysql.cj.util.StringUtils;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.*;
import java.util.stream.Collectors;

/**
 *
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService{

    @Autowired(required = false)
    private UserMapper userMapper;

    @Autowired(required = false)
    private UserRoleMapper userRoleMapper;

    @Autowired(required = false)
    private RoleMapper roleMapper;

    @Autowired(required = false)
    private RolePersMapper rolePersMapper;

    @Autowired(required = false)
    private PermissionMapper permissionMapper;

    //1.分页查询 -->查询所有 搜索
    @Override
    public ResponseResult selectPage(UserPageDTO userPageDTO) {
        System.out.println("----------------------------------------------");
        System.out.println("userPageDTO = " + userPageDTO);
        //接收从前端传来的数据:page limit
        Integer page = userPageDTO.getPage();   //当前页
        Integer limit = userPageDTO.getLimit(); //从前端传过来的 每一页显示多少条
        Page<User> userPage = new Page<>(page, limit);

        //创建查询条件构造器对象,通过lambda进行构建
        LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda();
        //
        /*
         * 模糊查询 like(boolean condition,SFunction<User,?> column,Object val)
         *   (1)condition:  用于指定当前条件是否有效，若是为true，则有效
         *       isEmptyOrWhitespaceOnly : 判定是否为空或为null
         *   (2)column:     要用于条件筛选的数据库表列名称，如：name
         *   (3)val:        用于指定数据表列的值，条件将根据该值进行筛选
         * */
        lambda.like(!StringUtils.isEmptyOrWhitespaceOnly(userPageDTO.getUsername()), User::getUsername,userPageDTO.getUsername())
                .like(!StringUtils.isEmptyOrWhitespaceOnly(userPageDTO.getCity()), User::getCity,userPageDTO.getCity() );
        /*
         * 根据 entity 条件，查询全部记录（并翻页）
         *
         * @param page         分页查询条件（可以为 RowBounds.DEFAULT）
         * @param queryWrapper 实体对象封装操作类（可以为 null）
         * */
        userMapper.selectPage(userPage, lambda);

        //查询所有分页的记录 (getRecords为Page.java封装的方法)
        List<User> users = userPage.getRecords();
        //总条数
        long total = userPage.getTotal();

        //将User类型-->转换为UserVO类型，因为UserVO里面有roles(角色)
        //遍历users，查询用户具有角色
        ArrayList<UserVO> userVOS = new ArrayList<>(); //将UserVO封装到到一个集合中
        users.forEach(user -> {
            //获取用户id (user表)
            Integer userId = user.getId();

            //根据用户id(user_id)，查询用户所有的角色id(role_id)
            QueryWrapper<UserRole> userRoleQueryWrapper = new QueryWrapper<>();
            userRoleQueryWrapper.eq("user_id", userId); //根据查询到的userId等于user_id
            //SELECT * FROM user_role WHERE user_id = userId
            List<UserRole> userRoles = userRoleMapper.selectList(userRoleQueryWrapper);

            //遍历userRoles，获取所有的角色id
            ArrayList<Integer> ids = new ArrayList<>();
            userRoles.forEach(userRole -> {
                Integer roleId = userRole.getRoleId();
                ids.add(roleId);
            });


            //根据角色id(role_id),查询用户的角色信息
            //查询（根据ID 批量查询）
            List<Role> roles = roleMapper.selectBatchIds(ids);
            //获取用户的角色名(字段comments)
            ArrayList<String> roleNames = new ArrayList<>();
            roles.forEach(role -> {
                roleNames.add(role.getComments());
            });

            //创建UserVo对象
            UserVO userVO = new UserVO();
            //对象的copy（将user->转换成userVO类型） 相当于userVO拥有user中的所有信息
            BeanUtils.copyProperties(user, userVO);
            userVO.setRoles(roleNames); //
            userVOS.add(userVO);

        });

        //封装响应数据
        ResponseResult responseResult = new ResponseResult();
        responseResult.setData(userVOS);
        responseResult.setMsg(CodeMsg.SELECT_SUCCESS.getMsg());
        responseResult.setCode(CodeMsg.SELECT_SUCCESS.getCode());
        responseResult.setCount(total);

        return responseResult;
    }

    //2.更新state状态值
    @Override
    public ResponseResult updateUserState(User user) {
        ResponseResult responseResult = new ResponseResult();
        userMapper.updateById(user);
        ////封装响应数据
        responseResult.setCode(CodeMsg.UPDATE_SUCCESS.getCode());
        responseResult.setMsg(CodeMsg.UPDATE_SUCCESS.getMsg());
        return responseResult;
    }

    //3.添加操作
    @Override
    public ResponseResult addUser(UserVO userVO) {

        ResponseResult responseResult = new ResponseResult();
        //(1)将用户信息，添加到user表中
        User user = new User();
        /*
         * BeanUtils.copyProperties
         * 将两个字段相同的对象进行属性值的复制。
         * 如果两个对象之间存在名称不相同的属性，
         * 则 BeanUtils 不对这些属性进行处理，需要程序手动处理*/
        //user中的存在的属性，userVO中一定要有，但是userVO中可以有多余的属性；
        BeanUtils.copyProperties(userVO, user);
        //判定用户是否存在(判定username是否存在)
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("username", user.getUsername());
        //SELECT id,username,password,salt,sex,tel,state,city,create_time,update_time FROM user WHERE (username = ?)
        User usr = userMapper.selectOne(userQueryWrapper);
        System.out.println("usr = " + usr);

        if(usr==null){ //如果username不存在，则添加用户-->此处相当于查重，存在就不添加用户
            //密码加密
            String salt = SaltUtil.getSalt(8);
            user.setSalt(salt); //设置随机8位数的盐，到用户user中
            String md5Pwd = new Md5Hash("888888", salt).toHex(); //设置初始密码888888+随机盐salt
            user.setPassword(md5Pwd);//将加密过后的密码，添加到用户user中

            //添加用户数据
            //INSERT INTO user ( username, sex, tel, city ) VALUES ( ?, ?, ?, ? )
            userMapper.insert(user);
            //获取用户角色信息，添加到user_role表中
            List<String> roles = userVO.getRoles();
            //根据角色(comments)查询角色id(role_id)
            LambdaQueryWrapper<Role> lambda = new QueryWrapper<Role>().lambda();
            lambda.in(Role::getComments,roles.toArray());
            //SELECT role_id,role_name,comments,create_time,update_time FROM role WHERE (comments IN (?,?))
            List<Role> rls = roleMapper.selectList(lambda);
            System.out.println("rls = " + rls);//-----------------------------------------

            //(2)将用户的角色信息，添加到user_role表中
            //获取用户id(user_id)
            Integer userId = user.getId();
            rls.forEach(rl->{
                UserRole userRole = new UserRole();
                userRole.setRoleId(rl.getRoleId());
                userRole.setUserId(userId);
                //INSERT INTO user_role ( user_id, role_id ) VALUES ( ?, ? )
                userRoleMapper.insert(userRole);
            });

            //封装响应数据
            responseResult.setMsg(CodeMsg.ADD_SUCCESS.getMsg());
            responseResult.setCode(CodeMsg.ADD_SUCCESS.getCode());


        }else{
            //用户已存在，返回提示信息
            responseResult.setMsg(CodeMsg.USER_EXIST.getMsg());
            responseResult.setCode(CodeMsg.USER_EXIST.getCode());
        }
        return responseResult;
    }

    //4.回显数据 根据id，查询用户信息
    @Override
    public ResponseResult getUserVOById(Integer id) {
        //查询用户基础信息
        User user = userMapper.selectById(id);
        //查询用户的角色id（根据用户user_id，查询角色role_id）
        QueryWrapper<UserRole> userRoleQueryWrapper = new QueryWrapper<>();
        userRoleQueryWrapper.eq("user_id", id);
        List<UserRole> userRoles = userRoleMapper.selectList(userRoleQueryWrapper);

        //遍历集合，获取角色id(role_id)
        ArrayList<Integer> roleIds = new ArrayList<>();
        userRoles.forEach(userRole -> {
            roleIds.add(userRole.getRoleId());
        });

        System.out.println("roleIds = " + roleIds);  //例如有两个角色:roleIds = [1, 2]

        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        userVO.setRoleIds(roleIds);

        System.out.println("userVO = " + userVO);  //userVO = UserVO(roles=null, roleIds=[1, 2])

        //封装响应数据
        ResponseResult responseResult = new ResponseResult();
        responseResult.setMsg(CodeMsg.SELECT_SUCCESS.getMsg());
        responseResult.setCode(CodeMsg.SELECT_SUCCESS.getCode());
        responseResult.setData(userVO);

        return responseResult;
    }

    //5.编辑操作
    @Override
    public ResponseResult updateUser(UserVO userVO) {
        //(1)用户表user --> 根据用户id，更新用户信息
        User user = new User();
        BeanUtils.copyProperties(userVO, user);
        userMapper.updateById(user);

        //(2)用户角色关联表user_role-->
        //删除当前用户的所有角色信息后，再重新添加新的角色信息
        Integer userId = user.getId();
        LambdaQueryWrapper<UserRole> lambda = new QueryWrapper<UserRole>().lambda();
        lambda.eq(UserRole::getUserId,userId);
        userRoleMapper.delete(lambda);
        //获取前端传来的所有角色信息
        List<Integer> roleIds = userVO.getRoleIds();
        roleIds.forEach(roleId->{
            UserRole userRole = new UserRole();
            userRole.setUserId(userId);
            userRole.setRoleId(roleId);
            userRoleMapper.insert(userRole);
        });

        //封装响应数据
        ResponseResult responseResult = new ResponseResult();
        responseResult.setMsg(CodeMsg.UPDATE_SUCCESS.getMsg());
        responseResult.setCode(CodeMsg.UPDATE_SUCCESS.getCode());

        return responseResult;
    }

    //6.删除操作
    @Override
    public ResponseResult deleteUser(String ids) {
        //System.out.println("ids = " + ids); //例如选中24和25，则打印: 24,25

        //将ids的字符串转换为 集合类型
        String[] idsStr = ids.split(",");
        ArrayList<Integer> intIds = new ArrayList<>();
        for (String s : idsStr) {
            //Integer.valueOf(s)把字符串s解析成Integer对象类型，返回的integer 可以调用对象中的方法。
            intIds.add(Integer.valueOf(s));
        }
        System.out.println("intIds = " + intIds);

        //删除user表中的数据
        userMapper.deleteBatchIds(intIds);
        //删除user_role表中的数据
        QueryWrapper<UserRole> userRoleQueryWrapper = new QueryWrapper<>();
        userRoleQueryWrapper.in("user_id", intIds);
        userRoleMapper.delete(userRoleQueryWrapper);

        //封装响应数据
        ResponseResult responseResult = new ResponseResult();
        responseResult.setMsg(CodeMsg.DELETE_SUCCESS.getMsg());
        responseResult.setCode(CodeMsg.DELETE_SUCCESS.getCode());

        return responseResult;
    }

    //7.加载菜单的方法
    @Override
    public Map<String, Object> loadMenu(String username) {


        /*
         * 格式可参照 api/init.json
         * {
         *   homeInfo:{}
         *   logoInfo:{}
         *   menuInfo:{}
         * }
         * */
        //菜单:menu
        HashMap<String, Object> map = new HashMap<>(16);
        //homeInfo
        HashMap<String, Object> home = new HashMap<>(16);
        //logoInfo
        HashMap<String, Object> logo = new HashMap<>(16);

        //数据初始化
        //(1)
        home.put("title", "首页");
        home.put("href", "main.html");
        map.put("homeInfo", home);

        //(2)
        logo.put("title", "教务管理系统");
        logo.put("image", "images/logo.png");
        map.put("logoInfo", logo);

        //(3)
        //根据用户名，查询用户的权限信息--->将查询到的数据结构调整为tree（tree数据树格式）

        //1.根据用户名(username)，查询用户id(id) -->操作user用户表
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("username", username);
        User user = userMapper.selectOne(userQueryWrapper);
        Integer userId = user.getId();
        System.out.println("userId = " + userId);

        //2.根据用户id(user_id),查询角色id(role_id)  -->操作user_role用户角色关联表
        QueryWrapper<UserRole> userRoleQueryWrapper = new QueryWrapper<>();
        userRoleQueryWrapper.in("user_id", userId);
        List<UserRole> userRoles = userRoleMapper.selectList(userRoleQueryWrapper);
        //将userRoles对象类型-->转换为集合类型
        /*
         * System.out.println("userRoles = " + userRoles);
         * 对象类型: userRoles = [UserRole(userId=24, roleId=1), UserRole(userId=24, roleId=2)]
         *
         * System.out.println("roleIds = " + roleIds);
         * 集合类型: roleIds = [1, 2]
         * */
        List<Integer> roleIds = userRoles.stream().map(userRole -> {
            return userRole.getRoleId();
        }).collect(Collectors.toList());

        //3.根据角色id(role_id),查询权限id(per_id)
        QueryWrapper<RolePers> rolePersQueryWrapper = new QueryWrapper<>();
        rolePersQueryWrapper.in("role_id", roleIds);
        List<RolePers> rolePers = rolePersMapper.selectList(rolePersQueryWrapper);
        //将rolePers对象类型-->转换为集合类型
        List<Integer> perIds = rolePers.stream().map(rp -> {
            return rp.getPerId();
        }).collect(Collectors.toList());
        System.out.println("perIds = " + perIds);

        //4.根据权限id(id)，查询权限的详细信息 -->只查询目录和菜单，按钮不需要查询
        QueryWrapper<Permission> permissionQueryWrapper = new QueryWrapper<>();
        permissionQueryWrapper.in("id",perIds)
                .in("is_menu", Arrays.asList(0,1));
        List<Permission> permissions = permissionMapper.selectList(permissionQueryWrapper);
        //将permissions对象类型-->转换为集合类型
        List<PermissionVO> permissionVOS = permissions.stream().map(permission -> {
            PermissionVO permissionVO = new PermissionVO();
            BeanUtils.copyProperties(permission, permissionVO);
            return permissionVO;
        }).collect(Collectors.toList());

        //5.将查询的数据的数据结构调整为tree（tree数据树格式）
        map.put("menuInfo", TreeUtil.toTree(permissionVOS, 0));

        return map;
    }


}




